﻿package kliment.controls {
	import caurina.transitions.Equations;
	import caurina.transitions.Tweener;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import kliment.utils._Sprite;
	/**
	 * ...
	 * @author	Kliment
	 * @version	0.0.2
	 * 
	 * class name: kliment.controls.ListBox
	 */
	public class ListBox {
		private var _target_mc:Sprite;
		private var _itemRender:Class;
		private var _dataProvider:*;
		private var _orientation:*;
		private var _list:Array;
		private var _width:Number;
		private var _height:Number;
		private var _hInterval:Number = 0;
		private var _vInterval:Number = 0;
		
		public var animationUpdate:Boolean = false;
		
		public function ListBox(target_mc:Sprite, orientation:*) {
			_target_mc = target_mc;
			_orientation = orientation;
			
		}
		
		public function get itemRender():Class { return _itemRender }
		public function set itemRender(className:Class) {
			_itemRender = className;
			if (_dataProvider)
				dataProvider = _dataProvider;
		}
		
		public function get dataProvider():* { return _dataProvider }
		public function set dataProvider(value:*):void {
			_dataProvider = value;
			if (!_itemRender) return;
			erase();
			_list = new Array();
			for each (var item:* in _dataProvider) 
				add(item);
		}
		
		public function add(data:*):void {
			var newItem:* = new _itemRender();
			newItem.index = _list.length;
			newItem.data = data;
			var pos:Point = _getPosition(_list.length);
			newItem.x = pos.x;
			newItem.y = pos.y;
			_list.push(newItem);
			_target_mc.addChild(newItem);
			_width = Math.max(_target_mc.width, _width);
			_height = Math.max(_target_mc.height ,_height);
		}
		
		public function remove(victim:*):void {
			var target:DisplayObject;
			if (victim is DisplayObject) {
				target = victim;
			} else if (victim >= 0) {
				target = _list[victim];
			} else {
				return;
			}
			
			var length:Number = _list.length;
			for (var i:Number = 0; i < length; ++i) {
				if (_list[i] == target) {
					Tweener.removeTweens(target);
					_Sprite.remove(target);
					_list.splice(i, 1);
					_updateFrom(i);
					break;
				}
			}
		}
		
		public function erase():void {
			if (!_list) return;
			while (_list.length > 0) 
				_Sprite.remove(_list.shift());
			//_nextId = 0;
		}
		
		public function update():void {
			_updateFrom(0);
		}
		
		private function _updateFrom(index:int):void {
			if (!_list) 
				return;
			var length:Number = _list.length;
			for (var i:int = index; i < length; ++i) {
				var pos:Point = _getPosition(i);
				var item:* = _list[i];
				item.index = i;
				if (!animationUpdate) {
					item.x = pos.x;
					item.y = pos.y;
				} else {
					var parameters:Object = { x:pos.x, y:pos.y, time:.5, transition:Equations.easeOutCubic };
					if (i == index) 
						parameters.onUpdate = _onUpdateAnimationHandler;
					Tweener.addTween(item, parameters);
				}
			}
		}
		
		private function _onUpdateAnimationHandler():void {
			
		}
		
		private function _getPosition(index:Number):Point {
			var result:Point;
			var nextX:Number = 0;
			var nextY:Number = 0;
			var length:Number = _list.length;
			for (var i:Number = 0; i < index; ++i) {
				var item:DisplayObject = _list[i];
				nextX += item.width + _hInterval;
				nextY += item.height + _vInterval;
			}
			switch(_orientation) {
				case Orientation.HORIZONTAL:
					result = new Point(nextX , 0);
				break;
				
				case Orientation.VERTICAL:
					result = new Point(0, nextY);
				break;
				
				case Orientation.TILE:
					trace("mode don't work! use: Orientation.HORIZONTAL or Orientation.VERTICAL");
				break;
			}
			return result;
		}
		
		public function getItem(index:Number):* {
			return _list[index];
		}
		
		public function get length():Number { return _list.length }
	
		public function get hInterval():Number { return _hInterval }
		public function set hInterval(value:Number):void {
			_hInterval = value;
			update();
		}
		
		public function get vInterval():Number { return _vInterval }
		public function set vInterval(value:Number):void {
			_vInterval = value;
			update();
		}
		
		public function get x():Number { return _target_mc.x }
		public function set x(value:Number):void { 
			_target_mc.x = value;
		}
		
		public function get y():Number { return _target_mc.y }
		public function set y(value:Number):void { 
			_target_mc.y = value;
		}
		
		public function get width():Number { return _width }
		public function set width(value:Number):void {
			value = Math.max(1, value);
			_width = value;
			
			if (_orientation == Orientation.VERTICAL){
				var len:Number = _list.length;
				for (var i:Number = 0; i < len; i++) {
					_list[i].width = _width;
				}
				update();
			}
		}
		
		public function get height():Number { return _height }
		public function set height(value:Number):void {
			value = Math.max(1, value);
			_height = value;
			
			if (_orientation == Orientation.HORIZONTAL){
				var len:Number = _list.length;
				for (var i:Number = 0; i < len; i++) {
					_list[i].height = _height;
				}
				update();
			}
		}
	}

}